﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Kinect_Interface_Prototype_1.Voice_Commands;

namespace Kinect_Interface_Prototype_1.Interface_Design
{
    public partial class ControlForm : Form
    {
        private Point mouseOffset = new Point();
        private bool mouseDown = false;
        private IniFile configINI;
        private IniFile settingsINI;
        private StartupProgram MainProgram;
        private string imageFolder = Constants.InterfaceImagesFolder;

        private ConfirmationWindow confirmationWindow;

        private OnOffSwitch gestureOnOff;
        private OnOffSwitch mouseControlOnOff;
        private OnOffSwitch voiceCommandsOnOff;
        private OnOffIndicator skeletalOnOff;

        private MenuItem showSettingsItem;
        private MenuItem showControlFormItem;
        private MenuItem resetControlFormItem;
        private MenuItem showAppDockItem;
        private MenuItem resetAppDockItem;
        private MenuItem exitSystemItem;

        NotifyIcon systemTrayIcon = new NotifyIcon();

        private Dictionary<OnOffControlType, OnOffControl> onOffControls;

        public ControlForm(StartupProgram program, ConfirmationWindow confirmationWindow)
        {
            InitializeComponent();
            this.FormBorderStyle = FormBorderStyle.None;

            configINI = new IniFile(Constants.InterfaceINI);
            settingsINI = new IniFile(Constants.SettingsINI);

            InitializeOnOffControls();
            InitailizeSystemTrayIcon();

            MainProgram = program;
            this.confirmationWindow = confirmationWindow;

            // Used to set the background of the form and its image to transparent
            this.BackColor = Color.Aqua;
            this.TransparencyKey = Color.Aqua;   
        }

        private void InitializeOnOffControls()
        {
            gestureOnOff = new OnOffSwitch(true, 39, 67);
            gestureOnOff.Click += new EventHandler(gestureControlOnOff_Click);
            mouseControlOnOff = new OnOffSwitch(39, 166);
            mouseControlOnOff.Click += new EventHandler(mouseControlOnOff_Click);
            voiceCommandsOnOff = new OnOffSwitch(39, 275);
            voiceCommandsOnOff.Click += new EventHandler(voiceCommandsOnOff_Click);
            skeletalOnOff = new OnOffIndicator(42, 392);

            onOffControls = new Dictionary<OnOffControlType, OnOffControl>
            {
                {OnOffControlType.GestureControl, gestureOnOff},
                {OnOffControlType.MouseControl, mouseControlOnOff},
                {OnOffControlType.VoiceCommands, voiceCommandsOnOff},
                {OnOffControlType.SkeletalTracking, skeletalOnOff}
            };

            foreach (OnOffControl onOffControl in onOffControls.Values)
            {
                this.Controls.Add(onOffControl);
            }

            // Set toggles to specified start positions
            switchToggle(OnOffControlType.GestureControl, Boolean.Parse(settingsINI.IniReadValue("General", "gestureControlOnStart")));
            switchToggle(OnOffControlType.MouseControl, Boolean.Parse(settingsINI.IniReadValue("General", "mouseControlOnStart")));
            switchToggle(OnOffControlType.VoiceCommands, Boolean.Parse(settingsINI.IniReadValue("General", "voiceCommandsStart")));
        }

        private void InitailizeSystemTrayIcon()
        {
            systemTrayIcon.Icon = new Icon(new FileStream(Constants.InterfaceImagesFolder + "kinect.ico", FileMode.Open, FileAccess.Read));
            systemTrayIcon.Visible = true;
            systemTrayIcon.Text = "Kinect Interface";

            showSettingsItem = new MenuItem("Show Settings Window", delegate(object sender, EventArgs e) { MainProgram.SettingsForm_ToggleVisibility(true); });
            showControlFormItem = new MenuItem("Hide Control Board", delegate(object sender, EventArgs e) { MainProgram.ControlForm_ToggleVisibility(); });
            resetControlFormItem = new MenuItem("Reset Control Board Location", delegate(object sender, EventArgs e) { this.ResetLocation(); });
            showAppDockItem = new MenuItem("Hide App Dock", delegate(object sender, EventArgs e) { MainProgram.AppDock_ToggleVisibility(); });
            resetAppDockItem = new MenuItem("Reset App Dock Location", delegate(object sender, EventArgs e) { MainProgram.AppDock_ResetLocation(); });
            exitSystemItem = new MenuItem("Exit System", delegate(object sender, EventArgs e) { MainProgram.ShutDown(); });

            ContextMenu systemTrayIconMenu = new ContextMenu();

            systemTrayIconMenu.MenuItems.Add(showSettingsItem);
            systemTrayIconMenu.MenuItems.Add("-");
            systemTrayIconMenu.MenuItems.Add(showControlFormItem);
            systemTrayIconMenu.MenuItems.Add(resetControlFormItem);
            systemTrayIconMenu.MenuItems.Add("-");
            systemTrayIconMenu.MenuItems.Add(showAppDockItem);
            systemTrayIconMenu.MenuItems.Add(resetAppDockItem);
            systemTrayIconMenu.MenuItems.Add("-");
            systemTrayIconMenu.MenuItems.Add(exitSystemItem);

            systemTrayIcon.ContextMenu = systemTrayIconMenu;
        }

        #region Control Form Load and Closing

        private void ControlForm_Load(object sender, EventArgs e)
        {
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = Screen.PrimaryScreen.Bounds.Height;

            int x = Int32.Parse(configINI.IniReadValue("ControlPanel", "startX"));
            int y = Int32.Parse(configINI.IniReadValue("ControlPanel", "startY"));

            int newX = x + this.Width > screenWidth || x < 0 ? screenWidth - this.Width : x;
            int newY = y + this.Height > screenHeight? (y < 0 ? 0 : screenHeight - this.Height) : (y < 0 ? 0 : y);

            this.Location = new Point(newX, newY);
        }

        private void ControlForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            configINI.IniWriteValue("ControlPanel", "startX", this.Location.X.ToString());
            configINI.IniWriteValue("ControlPanel", "startY", this.Location.Y.ToString());

            // Remove the system try icon
            systemTrayIcon.Dispose();
        }

        #endregion

        #region Control Form Movement Functions
        
        private void ControlForm_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                mouseOffset = new Point(-e.X - SystemInformation.FrameBorderSize.Width, -e.Y - SystemInformation.FrameBorderSize.Height);
                mouseDown = true;
            }
        }

        private void ControlForm_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                mouseDown = false;
        }

        private void ControlForm_MouseMove(object sender, MouseEventArgs e)
        {
            if (mouseDown)
            {
                Point mousePosition = Control.MousePosition;
                mousePosition.Offset(mouseOffset.X, mouseOffset.Y);
                this.Location = mousePosition;
            }
        }

        #endregion
        
        #region Control Form Button Event Functions

        private void settingsButton_MouseDown(object sender, MouseEventArgs e)
        {
            settingsButton.Image = Image.FromFile(imageFolder + "settingsButton_down.png");
        }

        private void settingsButton_MouseUp(object sender, MouseEventArgs e)
        {
            settingsButton.Image = Image.FromFile(imageFolder + "settingsButton.png");

            if (!MainProgram.SettingsForm_GetVisible())
                MainProgram.SettingsForm_ToggleVisibility(true);
        }

        private void powerButton_MouseDown(object sender, MouseEventArgs e)
        {
            powerButton.Image = Image.FromFile(imageFolder + "powerButton_down.png");
        }

        private void powerButton_MouseUp(object sender, MouseEventArgs e)
        {
            powerButton.Image = Image.FromFile(imageFolder + "powerButton.png");

            if(!confirmationWindow.Visible)
            {
                confirmationWindow.command = "exit";
                confirmationWindow.textLabel.Text = "Are you sure you want to exit the system?";
                confirmationWindow.Show();
            }
        }

        #endregion

        #region Control Form OnOff Switch Click Event Handlers
        
        private void gestureControlOnOff_Click(object sender, EventArgs e)
        {
            MainProgram.KinectForm_ToggleGestureControl(gestureOnOff.State);
        }

        private void mouseControlOnOff_Click(object sender, EventArgs e)
        {
            MainProgram.KinectForm_ToggleMouseControl(mouseControlOnOff.State);
        }

        private void voiceCommandsOnOff_Click(object sender, EventArgs e)
        {
            MainProgram.VoiceCommands_ToggleActive(voiceCommandsOnOff.State);
        }

        #endregion

        private void switchToggle(OnOffControlType onOffControl, bool On)
        {
            onOffControls[onOffControl].ToggleState(On);
        }

        // Public Functions
        public void SetShowControlFormItemText(string text)
        {
            showControlFormItem.Text = text;
        }

        public void SetShowAppDockItemText(string text)
        {
            showAppDockItem.Text = text;
        }

        public void ToggleSwitch(OnOffControlType onOffControl, bool On)
        {
            onOffControls[onOffControl].ToggleState(On);
        }

        public void SwitchOn(OnOffControlType onOffControl)
        {
            ToggleSwitch(onOffControl, true);
        }

        public void SwitchOff(OnOffControlType onOffControl)
        {
            ToggleSwitch(onOffControl, false);
        }

        public bool GetSwitchOn(OnOffControlType onOffSwitch)
        {
            return onOffControls[onOffSwitch].State;
        }

        public void ResetLocation()
        {
            this.SetDesktopLocation(Screen.PrimaryScreen.Bounds.Width / 2, Screen.PrimaryScreen.Bounds.Height / 2 - this.Height/2);
        }

        public void ActivateSwitch(OnOffControlType onOffControlType, bool active)
        {
            ((OnOffSwitch)onOffControls[onOffControlType]).Active = active;
        }
    }
}
